#ifndef __INSTRUCTION_H
#define __INSTRUCTION_H 1

#include <string>
#include <cstdio>

#define MIPS_EXIT   (~0u)

struct Instruction {
private:
public:
    const uint32_t _i;

    explicit Instruction(uint32_t i) : _i(i) {}
    bool nop() const { return _i == 0; }
    bool exit() const { return _i == MIPS_EXIT; }

    uint32_t op() const {return _i>>26;};
    uint32_t shamt() const {return (_i>>6) & 0x1F;}
    uint32_t func() const { return _i & 0x3F;}


    uint32_t J() const {return _i & 0x3FFFFFF;}
    // unsigned immediate
    uint32_t uimm() const { return _i & 0xFFFF;}
    // signed immediate
    int32_t simm() const { return (int16_t)(_i & 0xFFFF);}

    uint32_t rs() const { return (_i >> 21) & 0x1F;}
    uint32_t rt() const { return (_i >> 16) & 0x1F;}
    uint32_t rd() const { return (_i >> 11) & 0x1F;}

};


static_assert(sizeof(Instruction) == 4, "instruction length must be 4!");


#endif // __INSTRUCTION_H
